﻿
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using YS.K12.Application.IoT.CommandHandler;
using YS.K12.Core.IoT.Adapter;
using YS.K12.Core.IoT.Plugin;
using CSRedis;
using YS.Domain.IoT.Option;
using NLog.Web;
using NLog;
using Microsoft.Extensions.Logging;
using Yitter.IdGenerator;
using MagicOnion.Server;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using System.Net;
using Microsoft.AspNetCore.Http;
using YS.K12.IoT.Startup;
using Flurl.Http;
using Masuit.Tools;
namespace YS.K12.IoT
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var remoteIPHost = AppSettingsHelper.GetContent("IHttp", "Vend", "Address");
            Console.WriteLine($"读取的配置：{AppSettingsHelper.GetContent("Iot-Redis-Main")}||{remoteIPHost}||{AppSettingsHelper.GetContent("SocketListen")}");
            // 注册 CodePagesEncodingProvider 以便使用 GB2312 编码
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();

            var builder = WebApplication.CreateBuilder(args);
            // var builder = Host.CreateApplicationBuilder(args);
            builder.Logging.ClearProviders();// 清除默认的日志提供程序
            builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug);// 设置最小日志级别
            builder.Host.UseNLog();
            // 配置 gRPC 和 MagicOnion
            builder.WebHost.ConfigureKestrel(options =>
            {
                var port = AppSettingsHelper.GetContent("GrpcHttp2Listen", "Port").ToInt32();
                var ip = AppSettingsHelper.GetContent("GrpcHttp2Listen", "IP");
                options.Listen(IPAddress.Any, port, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                });
            });
            // 设置雪花id的workerId，确保每个实例workerId都应不同
            var workerId = AppSettingsHelper.GetContent("SnowId","WorkerId");
            YitIdHelper.SetIdGenerator(new IdGeneratorOptions { WorkerId = ushort.Parse(workerId) });
            //builder.Services.AddHostedService<Worker>();//后台工作
            builder.Services.AddEventBus(op => 
            {
                // 注册 ToDo 事件订阅者
                op.AddSub();
                op.ChannelCapacity = 4000;
                op.AddMonitor<CommandFilter>();
                op.UnobservedTaskExceptionHandler = (obj, args) =>
                {
                    logger.Error(args.Exception.InnerException, args.Exception.Message);
                };
            });
            //服务依赖注入
            builder.Services.AddInjection();
            RedisHelper.Initialization(new CSRedisClient(AppSettingsHelper.GetContent("Iot-Redis-Main")));
            builder.Services.AddTcpService(config =>
            {
                var addr = AppSettingsHelper.GetContent("SocketListen");
                var prot= addr.Split(":")[2].ToInt32();
                config.SetListenIPHosts(prot)
                .SetMaxCount(20000)//最大连接数
                .SetGetDefaultNewId(() => Guid.NewGuid().ToString())//使用Guid作为初始Id。
                .SetTcpDataHandlingAdapter(() => new YsBetweenAndDataHandlingAdapter())
                .ConfigureContainer(a =>//容器的配置顺序应该在最前面
                {

                }).ConfigurePlugins(a =>
                {
                    //心跳检测
                    a.UseCheckClear()
                    .SetCheckClearType(CheckClearType.OnlyReceive)
                    .SetTick(TimeSpan.FromSeconds(180))//秒
                    .SetOnClose((c, t) =>
                    {
                        c.TryShutdown();
                        c.SafeClose("超时无数据");
                    });
                    a.Add<ServerPlugin>();
                    a.Add<TcpConnectPlugin>();
                    a.Add<TcpReceivedPlugin>();
                    a.Add<TcpSendingPlugin>();
                });
            });

            //增加Grpc
            builder.Services.AddGrpc();
            builder.Services.AddMagicOnion();
            var app = builder.Build();
            // 配置 HTTP 请求管道
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapMagicOnionService();

                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
         
                });
            });
            app.Run();
        }
    }
}
